home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
disasm.zip
/
ASMTUTR3.DOC
< prev
next >
Wrap
Text File
|
1988-06-03
|
19KB
|
338 lines
PROGPREF SEGMENT AT 0 ;Really a DSECT mapping the program prefix
ORG PROGPREF+6
MEMSIZE DW ? ;Size of available memory
PROGPREF ENDS
Really, no matter whether the AT value represents truth or fiction, it is
your responsibility, not the assembler's, to get set up a segment register
so that you can really reach the storage in question. So, you can't say
MOV AL,EQUIP
unless you first say something like
MOV AX,BIOSAREA ;BIOSAREA becomes a symbol with value 40H
MOV ES,AX
ASSUME ES:BIOSAREA
Enough about SEGMENT. The END statement is simple. It goes at the end of
every assembly. When you are assembling a subroutine, you just say
END
but when you are assembling the main routine of a program you say
END label
where 'label' is the place where execution is to begin.
Another pseudo-op illustrated in the program is ASSUME. ASSUME is like the
USING statement in 370 assembler. However, ASSUME can ONLY refer to seg-
ment registers. The assembler uses ASSUME information to decide whether to
assemble segment override prefixes and to check that the data you are try-
ing to access is really accessible. In this case, we can reassure the
assembler that both the CS and DS registers will address the section called
HELLO at execution time. Actually, the SS and ES registers will too, but
the assembler never needs to make use of this information.
I guess I have explained everything in the program except that ORG
pseudo-op. ORG means the same thing as it does in many assembly languages.
It tells the assembler to move its location counter to some particular
address. In this case, we have asked the assembler to start assembling
code hex 100 bytes from the start of the section called HELLO instead of at
the very beginning. This simply reflects the way COM programs are loaded.
When a COM program is loaded by the system, the system sets up all four
segment registers to address the same 64K of storage. The first 100 hex
bytes of that storage contains what is called the program prefix; this area
is described in appendix E of the DOS manual. Your COM program physically
begins after this. Execution begins with the first physical byte of your
program; that is why the JMP instruction is there.
Wait a minute, you say, why the JMP instruction at all? Why not put the
data at the end? Well, in a simple program like this I probably could have
gotten away with that. However, I have the habit of putting data first and
would encourage you to do the same because of the way the assembler has of
assembling different instructions depending on the nature of the operand.
IBM PC Assembly Language Tutorial 19
Unfortunately, sometimes the different choices of instruction which can
assemble from a single opcode have different lengths. If the assembler has
already seen the data when it gets to the instructions it has a good chance
of reserving the right number of bytes on the first pass. If the data is
at the end, the assembler may not have enough information on the first pass
to reserve the right number of bytes for the instruction. Sometimes the
assembler will complain about this, something like "Forward reference is
illegal" but at other times, it will make some default assumption. On the
second pass, if the assumption turned out to be wrong, it will report what
is called a "Phase error," a very nasty error to track down. So get in the
habit of putting data and equated symbols ahead of code.
OK. Maybe you understand the program now. Let's walk through the steps
involved in making it into a real COM file.
1. The file should be created with the name HELLO.ASM (actually the name
is arbitrary but the extension .ASM is conventional and useful)
2.
ASM HELLO,,;
(this is just one example of invoking the assembler; it uses the small
assembler ASM, it produces an object file and a listing file with the
same name as the source file. I am not going exhaustively into how to
invoke the assembler, which the manual goes into pretty well. I guess
this is the first time I mentioned that there are really two
assemblers; the small assembler ASM will run in a 64K machine and
doesn't support macros. I used to use it all the time; now that I have
a bigger machine and a lot of macro libraries I use the full function
assembler MASM. You get both when you buy the package).
3. If you issue DIR at this point, you will discover that you have
acquired HELLO.OBJ (the object code resulting from the assembly) and
HELLO.LST (a listing file). I guess I can digress for a second here
concerning the listing file. It contains TAB characters. I have found
there are two good ways to get it printed and one bad way. The bad way
is to use LPT1: as the direct target of the listing file or to try
copying the LST file to LPT1 without first setting the tabs on the
printer. The two good ways are to either
a. direct it to the console and activate the printer with CTRL-PRTSC.
In this case, DOS will expand the tabs for you.
b. direct to LPT1: but first send the right escape sequence to LPT1 to
set the tabs every eight columns. I have found that on some early
serial numbers of the IBM PC printer, tabs don't work quite right,
which forces you to the first option.
4.
LINK HELLO;
(again, there are lots of linker options but this is the simplest. It
takes HELLO.OBJ and makes HELLO.EXE). HELLO.EXE? I thought we were
IBM PC Assembly Language Tutorial 20
making a COM program, not an EXE program. Right. HELLO.EXE isn't
really executable; its just that the linker doesn't know about COM pro-
grams. That requires another utility. You don't have this utility if
you are using DOS 1.0; you have it if you are using DOS 1.1 or DOS 2.0.
Oh, by the way, the linker will warn you that you have no stack
segment. Don't worry about it.
5.
EXE2BIN HELLO HELLO.COM
This is the final step. It produces the actual program you will exe-
cute. Note that you have to spell out HELLO.COM; for a nominally
rational but actually perverse reason, EXE2BIN uses the default exten-
sion BIN instead of COM for its output file. At this point, you might
want to erase HELLO.EXE; it looks a lot more useful than it is.
Chances are you won't need to recreate HELLO.COM unless you change the
source and then you are going to have to redo the whole thing.
6.
HELLO
You type hello, that invokes the program, it says
HELLO YOURSELF!!!
(oops, what did I do wrong....?)
What about subroutines?
_______________________
What about subroutines?
What about subroutines?
What about subroutines?
I started with a simple COM program because I actually think they are easi-
er to create than subroutines to be called from high level languages, but
maybe its really the latter you are interested in. Here, I think you
should get comfortable with the assembler FIRST with little exercises like
the one above and also another one which I will finish up with.
Next you are ready to look at the interface information for your particular
language. You usually find this in some sort of an appendix. For example,
the BASIC manual has Appendix C on Machine Language Subroutines. The
PASCAL manual buries the information a little more deeply: the interface
to a separately compiled routine can be found in the Chapter on Procedures
and Functions, in a subsection called Internal Calling Conventions.
Each language is slightly different, but here are what I think are some
common issues in subroutine construction.
1. NEAR versus FAR? Most of the time, your language will probably call
your assembler routine as a FAR routine. In this case, you need to
make sure the assembler will generate the right kind of return. You do
this with a P